<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
namespace App\Exception\Handler;

use App\Exception\FooException;
use App\Service\ErrorPoliceService;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\ExceptionHandler\ExceptionHandler;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\Utils\ApplicationContext;
use Psr\Http\Message\ResponseInterface;
use Throwable;

class AppExceptionHandler extends ExceptionHandler
{
    /**
     * @var StdoutLoggerInterface
     */
    protected $logger;

    public function __construct(StdoutLoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    public function handle(Throwable $throwable, ResponseInterface $response)
    {
        $container = ApplicationContext::getContainer();
        $request = $container->get(RequestInterface::class);

        $method = $request->getMethod();
        $action = $request->getRequestUri();
        $url = $request->url();
        $params = $request->all();

        //致命错误
        $arr = [
            'methon' => $method,
            'action' => $action,
            'url'    => $url,
            'params' => $params,
            'getCode' => $throwable->getCode(),
            'getMessage' => $throwable->getMessage(),
            'getLine' => $throwable->getLine(),
            'getFile' => $throwable->getFile(),
            'getTraceAsString' => $throwable->getTraceAsString(),
        ];

        $error = "";
        $error .= 'method => '.$method."<br>";
        $error .= 'action => '.$action."<br>";
        $error .= 'url => '.$url."<br>";
        $error .= 'params => '.json_encode($params, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)."<br>";
        $error .= '错误级别 => '."程序致命错误"."<br>";
        $error .= '错误编号 => '.$throwable->getCode()."<br>";
        $error .= '错误信息 => '.$throwable->getMessage()."<br>";
        $error .= '错误文件 => '.$throwable->getFile()."<br>";
        $error .= '错误行号 => '.$throwable->getLine()."<br>";
        $error .= '追踪痕迹 => '.$throwable->getTraceAsString()."<br>";
        zlog('error', $error);
        var_dump($arr);

        //TODO 判断环境报警
        $appEnv = env('APP_ENV');
        $emailPolice = env('EMAIL_POLICE', 'false');
        if (in_array($appEnv, ['local', 'dev']) && $emailPolice == true && $throwable->getCode() != 999) {
            //'1085562810@qq.com', '3veryou@sian.cn', '805527587@qq.com'
            $to = ['1085562810@qq.com'];
            //$to = ['jiangyongwei@banchengyun.com', '805527587@qq.com'];
            $subject = $appEnv.'_hyperf-skeleton项目错误';
            make(ErrorPoliceService::class)->push($to, $subject, $error, 3);
        }
        $this->logger->error(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile()));
        $this->logger->error($throwable->getTraceAsString());
        return $response->withHeader('Server', 'Hyperf')->withStatus(500)->withBody(new SwooleStream('Internal Server Error.'));
    }

    public function isValid(Throwable $throwable): bool
    {
        return true;
    }
}
